在之前的介紹中,我們提到 Web Application 需要負責驗證Request 與 Response 中的 JSON 資料。如果缺乏這樣的驗證步驟,可能會導致資料更新錯誤,或是回傳不完整的信息給使用者。這個概念同樣適用於 Command Line Application,它們也必須確保使用者提供的選項與參數正確無誤。
在之前開發 Web Application 時,我們使用了 FastAPI 框架,該套件內建了資料驗證功能。而 FastAPI 的貢獻者們後來也推出了一個號稱「it's the FastAPI of CLIs」的工具,專門用來處理 Command Line Application 的需求。
接下來,我同樣以前篇範例的 git command line 作為範例。
本次範例使用的是 Typer 0.12.5 版本
poetry add typer==0.12.5
Typer 提供了許多與 Click 類似的功能,例如支援群組(Group)、選項處理,以及註解說明。因此,前篇與本篇的範例程式碼有很多相似之處。最大的不同點在於 Typer 的參數型別提示。與 Click 不同的是,Typer 會自動驗證使用者提供的參數是否符合指定的型別,並在必要時進行型別轉換,這使得應用程式更加安全和可靠。
首先,我們將建立一個名為 git.py
的檔案,並宣告一個名為 app 的群組,將所有與 Git 相關的指令都納入此群組中。第一個要宣告的指令是 commit
,可以看到幾乎所有的內容都與前篇的 Click 範例相似,唯一的不同在於 message
增加了型別提示。在這裡,我們使用 Annotated 來提供型別提示。Annotated 是一種用於將 metadata附加到變數的工具,使開發者能在型別提示的基礎上,為變數提供更多的上下文資訊。
在本範例中,message
的型別提示為字串,並且它是一個選項(Option)。選項是透過 --
前綴傳入的附加輸入值,通常不是必需的,並且可以在命令中以任何順序提供。選項內宣告的第一個參數 ...
表示該選項為必填項,這裡之所以將選項設為必填,主要是為了方便教學,通常在實際應用中不建議這樣做。後續的參數分別是選項的名稱 --message
、選項的縮寫 -m
,以及提示說明。
接下來,我們將新增第二個指令 add
,其 path
的型別提示為字串陣列,並且它是一個參數(Argument)。參數是命令中必須提供的輸入值,並不需要前置的標記 --
,可以直接按照順序傳入。
from typing import Annotated
import typer
app = typer.Typer()
@app.command()
def commit(
message: Annotated[str, typer.Option(..., '--message', '-m', help='Commit message')]
):
"""
Record changes to the repository.
"""
typer.echo(f'[master (root-commit) 1234567] {message}')
typer.echo(' 1 file changed, 1 insertion(+), 0 deletions(-)')
@app.command()
def add(
paths: Annotated[list[str], typer.Argument(help="Files or directories to add to the index.")]
):
"""
Add file contents to the index.
"""
for path in paths:
typer.echo(f'Added {path} to the index.')
if __name__ == "__main__":
app()
使用者可以執行 poetry run python git.py --help
即可看到 git 的使用說明
使用者可以執行 poetry run python git.py add hello.md test.py
即可看到 add 成功的結果
使用者可以執行 poetry run python git.py commit -m "Test"
即可看到 commit 成功的結果